{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn import metrics, datasets\n",
    "from sklearn.semi_supervised import LabelSpreading\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 加载数据 这里使用sklearn自带的糖尿病数据\n",
    "def load_data():\n",
    "    '''\n",
    "    加载数据集\n",
    "    返回一个元祖，依次是：样本集合、样本标记集合、未标记样本的下标集合\n",
    "    '''\n",
    "    digits = datasets.load_digits()\n",
    "    ### 混洗样本 ###\n",
    "    rng = np.random.RandomState(0)\n",
    "    indices = np.arange(len(digits.data)) # 样本的下标集合\n",
    "    \n",
    "    rng.shuffle(indices) # 混洗样本下标集合\n",
    "    X = digits.data[indices]\n",
    "    Y = digits.target[indices]\n",
    "    ### 生成未标记样本的下标集合 ###\n",
    "    n_labeled_points = int(len(Y)/10)  # 总样本数除以10 ，即只有十分之一的数据有标记\n",
    "    unlabeled_indices = np.arange(len(Y))[n_labeled_points:] # 其余的样本未标记\n",
    "    \n",
    "    return X, Y, unlabeled_indices"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy:0.972806\n"
     ]
    }
   ],
   "source": [
    "def test_LabelSpreading(*data):\n",
    "    '''\n",
    "    测试 LabelSpreading 的用法\n",
    "\n",
    "    :param data: 一个元组，依次为： 样本集合、样本标记集合、 未标记样本的下标集合\n",
    "    :return: None\n",
    "    '''\n",
    "    X,y,unlabeled_indices=data\n",
    "    y_train=np.copy(y) # 必须拷贝，后面要用到 y\n",
    "    y_train[unlabeled_indices]=-1 # 未标记样本的标记设定为 -1\n",
    "    clf=LabelSpreading(max_iter=100,kernel='rbf',gamma=0.1)\n",
    "    clf.fit(X,y_train)\n",
    "    ### 获取预测准确率\n",
    "    predicted_labels = clf.transduction_[unlabeled_indices] # 预测标记\n",
    "    true_labels = y[unlabeled_indices] # 真实标记\n",
    "    print(\"Accuracy:%f\"%metrics.accuracy_score(true_labels,predicted_labels))\n",
    "    # 或者 print(\"Accuracy:%f\"%clf.score(X[unlabeled_indices],true_labels))\n",
    "\n",
    "X, Y, unlabeled_indices = load_data()\n",
    "test_LabelSpreading(X, Y, unlabeled_indices)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.6/site-packages/sklearn/semi_supervised/label_propagation.py:293: RuntimeWarning: invalid value encountered in true_divide\n",
      "  self.label_distributions_ /= normalizer\n",
      "/usr/local/lib/python3.6/site-packages/sklearn/semi_supervised/label_propagation.py:288: ConvergenceWarning: max_iter=100 was reached without convergence.\n",
      "  category=ConvergenceWarning\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# rbf核 及其参数的影响\n",
    "def test_LabelSpreading_rbf(*data):\n",
    "    '''\n",
    "    测试 LabelSpreading 的 rbf 核时，预测性能随 alpha 和 gamma 的变化\n",
    "\n",
    "    :param data: 一个元组，依次为： 样本集合、样本标记集合、 未标记样本的下标集合\n",
    "    :return: None\n",
    "    '''\n",
    "    X,y,unlabeled_indices=data\n",
    "    y_train=np.copy(y) # 必须拷贝，后面要用到 y\n",
    "    y_train[unlabeled_indices]=-1 # 未标记样本的标记设定为 -1\n",
    "\n",
    "    fig=plt.figure()\n",
    "    ax=fig.add_subplot(1,1,1)\n",
    "    alphas=np.linspace(0.01,0.99,num=10,endpoint=True)\n",
    "    gammas=np.logspace(-2,2,num=50)\n",
    "    colors=((1,0,0),(0,1,0),(0,0,1),(0.5,0.5,0),(0,0.5,0.5),(0.5,0,0.5),\n",
    "        (0.4,0.6,0),(0.6,0.4,0),(0,0.6,0.4),(0.5,0.3,0.2),) # 颜色集合，不同曲线用不同颜色\n",
    "    ## 训练并绘图\n",
    "    for alpha,color in zip(alphas,colors):\n",
    "        scores=[]\n",
    "        for gamma in gammas:\n",
    "            clf=LabelSpreading(max_iter=100,gamma=gamma,alpha=alpha,kernel='rbf')\n",
    "            clf.fit(X,y_train)\n",
    "            scores.append(clf.score(X[unlabeled_indices],y[unlabeled_indices]))\n",
    "        ax.plot(gammas,scores,label=r\"$\\alpha=%s$\"%alpha,color=color)\n",
    "\n",
    "    ### 设置图形\n",
    "    ax.set_xlabel(r\"$\\gamma$\")\n",
    "    ax.set_ylabel(\"score\")\n",
    "    ax.set_xscale(\"log\")\n",
    "    ax.legend(loc=\"best\")\n",
    "    ax.set_title(\"LabelSpreading rbf kernel\")\n",
    "    plt.show()\n",
    "    \n",
    "\n",
    "X, Y, unlabeled_indices = load_data()\n",
    "test_LabelSpreading_rbf(X, Y, unlabeled_indices)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.6/site-packages/sklearn/semi_supervised/label_propagation.py:293: RuntimeWarning: invalid value encountered in true_divide\n",
      "  self.label_distributions_ /= normalizer\n",
      "/usr/local/lib/python3.6/site-packages/sklearn/semi_supervised/label_propagation.py:288: ConvergenceWarning: max_iter=100 was reached without convergence.\n",
      "  category=ConvergenceWarning\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def test_LabelSpreading_knn(*data):\n",
    "    '''\n",
    "   测试 LabelSpreading 的 knn 核时，预测性能随 alpha 和 n_neighbors 的变化\n",
    "\n",
    "\n",
    "    :param data:  一个元组，依次为： 样本集合、样本标记集合、 未标记样本的下标集合\n",
    "    :return:  None\n",
    "    '''\n",
    "    X,y,unlabeled_indices=data\n",
    "    y_train=np.copy(y) # 必须拷贝，后面要用到 y\n",
    "    y_train[unlabeled_indices]=-1 # 未标记样本的标记设定为 -1\n",
    "\n",
    "    fig=plt.figure()\n",
    "    ax=fig.add_subplot(1,1,1)\n",
    "    alphas=np.linspace(0.01,0.99,num=10,endpoint=True)\n",
    "    Ks=[1,2,3,4,5,8,10,15,20,25,30,35,40,50]\n",
    "    colors=((1,0,0),(0,1,0),(0,0,1),(0.5,0.5,0),(0,0.5,0.5),(0.5,0,0.5),\n",
    "        (0.4,0.6,0),(0.6,0.4,0),(0,0.6,0.4),(0.5,0.3,0.2),) # 颜色集合，不同曲线用不同颜色\n",
    "    ## 训练并绘图\n",
    "    for alpha,color in zip(alphas,colors):\n",
    "        scores=[]\n",
    "        for K in Ks:\n",
    "            clf=LabelSpreading(kernel='knn',max_iter=100,n_neighbors=K,alpha=alpha)\n",
    "            clf.fit(X,y_train)\n",
    "            scores.append(clf.score(X[unlabeled_indices],y[unlabeled_indices]))\n",
    "        ax.plot(Ks,scores,label=r\"$\\alpha=%s$\"%alpha,color=color)\n",
    "\n",
    "    ### 设置图形\n",
    "    ax.set_xlabel(r\"$k$\")\n",
    "    ax.set_ylabel(\"score\")\n",
    "    ax.legend(loc=\"best\")\n",
    "    ax.set_title(\"LabelSpreading knn kernel\")\n",
    "    plt.show()\n",
    "    \n",
    "data=load_data() # 获取半监督分类数据集\n",
    "test_LabelSpreading_knn(*data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
